import os
import logging
import dbus
import random
import serial
from xml.dom import minidom

UNKNOWN_DEVICE_TYPE = 0
GPS_DEVICE_TYPE = 1
BOAD_RATES = (4800,  9600,  19200,  38400)

class DiscoveryProvider:
    
    def getDiscoveredDevices(self):
        pass

class UserDefinedDiscoveryProvider(DiscoveryProvider):
    
    def __init__(self,  confContext):
        self.logger = logging.getLogger("socf") 
        self.mappings = os.path.join(confContext.getConfRootPath(),  "discovery.xml")
        self.logger.info("user defined discovery mapping file=%s" % self.mappings)

    def getDiscoveredDevices(self):
        deviceList = []
        xmldoc = minidom.parse(self.mappings)
        devices = xmldoc.getElementsByTagName("device")
        for device in devices:
            type = int(device.getElementsByTagName("device-type")[0].firstChild.data)
            path = device.getElementsByTagName("device-path")[0].firstChild.data
            id = device.getElementsByTagName("device-id")[0].firstChild.data
            deviceList.append((type,  path,  id))
        return deviceList
        
class HALDiscoveryProvider(DiscoveryProvider):
    
    def __init__(self,  confContext):
        self.logger = logging.getLogger("socf") 
        self.logger.info("hal discovery provider initliased")
        self.bus = dbus.SystemBus()
        self.hal_obj = self.bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
        self.hal = dbus.Interface(self.hal_obj, 'org.freedesktop.Hal.Manager')

    def getDiscoveredDevices(self):
        deviceList = []
        udis = self.hal.FindDeviceByCapability('serial')
        for udi in udis:
            dev_obj = self.bus.get_object ('org.freedesktop.Hal', udi)
            dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
            if str(dev.GetProperty('serial.type')) != "usb":
                continue
            path = str(dev.GetProperty('serial.device'))
            info = self.__getDeviceInfo(path)
            if info[0] == UNKNOWN_DEVICE_TYPE:
                continue
            path += ":" + str(info[2])
            id = "HAL_%s_%d" % (info[1], random.randint(100, 1000000))
            type =info[0]
            deviceList.append((type,  path,  id))
        return deviceList
        
    def __getDeviceInfo(self,  path):
        try:
            for br in BOAD_RATES:
                ser = serial.Serial(path, br, timeout=0.3)
                data = ser.read(100) # skip any non ascii that may be there
                data = ser.read(100)
                if self.__isAscii(data):
                    if data.find("$GP") != -1:
                        ser.close()
                        return (GPS_DEVICE_TYPE,  "GPS",  br)
                ser.close()
        except Exception, ex:
            self.logger.error("Error in getting device info for " + path + " - " + str(ex))
        return (UNKNOWN_DEVICE_TYPE,  "",  0)

    def __isAscii(self,  data):
        for d in data:
            if ord(d) > 127:
                return False
        return True

